package com.whfc.mach.manager.impl;

import com.alibaba.fastjson.JSON;
import com.whfc.common.constant.QueueConst;
import com.whfc.common.enums.DelFlag;
import com.whfc.common.enums.FenceType;
import com.whfc.common.spring.AppContextUtil;
import com.whfc.common.third.map.MapApi;
import com.whfc.common.third.map.MapLoc;
import com.whfc.common.util.DateUtil;
import com.whfc.common.util.JSONUtil;
import com.whfc.common.util.MathUtil;
import com.whfc.common.util.PositionUtil;
import com.whfc.influx.dao.AppMachDataLogDao;
import com.whfc.mach.dao.*;
import com.whfc.mach.dto.*;
import com.whfc.mach.dto.iot.MachWarnRotation;
import com.whfc.mach.dto.warn.MachWarnCheckDTO;
import com.whfc.mach.entity.*;
import com.whfc.mach.enums.NetState;
import com.whfc.mach.enums.WorkState;
import com.whfc.mach.manager.*;
import com.whfc.mach.manager.strategy.oil.OilStrategy;
import com.whfc.mach.manager.strategy.work.WorkStrategy;
import com.whfc.mach.manager.util.MachSegmentUtil;
import com.whfc.mach.manager.util.MachUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author sun_guodong
 * @description
 * @date 2020-12-02
 */
@Service
public class MachDataManagerImpl implements MachDataManager {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private AppMachDayMapper machDayMapper;

    @Autowired
    private AppMachDaySegMapper appMachDaySegMapper;

    @Autowired
    private AppMachDataMapper appMachDataMapper;

    @Autowired
    private AppMachDeviceMapper machDeviceMapper;

    @Autowired
    private AppDeviceMachDataMapper deviceMachDataMapper;

    @Autowired
    private MachDataLogManager machDataLogManager;

    @Autowired
    private MachStrategyMgr machStrategyMgr;

    @Autowired
    private MachMgr machMgr;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private MachConfigManager machConfigManager;

    @Autowired
    private AppMachDataLogDao appMachDataLogDao;

    @Autowired
    private AppMachMapper appMachMapper;

    @Autowired
    private AppMachOilLogMapper appMachOilLogMapper;

    @Autowired
    private MapApi mapApi;


    /**
     * 中化项目id
     */
    private static final int ZH_PROJECT_ID = 323;

    @Override
    public void initMachData(Integer machId) {
        this.initMachData(machId, null);
    }

    @Override
    public void initMachData(Integer machId, Integer deviceId) {
        AppMachData record = new AppMachData();
        record.setMachId(machId);
        if (deviceId != null) {
            record.setDeviceId(deviceId);
        }
        record.setTime(new Date());
        record.setNetState(com.whfc.common.enums.NetState.OFFLINE.getValue());
        record.setDelFlag(DelFlag.UNDELETE.getValue());
        record.setWorkState(com.whfc.common.enums.WorkState.STOP.getValue());
        appMachDataMapper.insertOrUpdate(record);
    }

    @Override
    public void addMachData(List<AppMachDataLog> logList) {

        if (logList.size() == 0) {
            return;
        }

        //查询与硬件绑定的机械
        Date serverTime = new Date();
        AppMachDataLog lastLog = logList.get(logList.size() - 1);
        Integer deviceId = lastLog.getDeviceId();
        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByDeviceId(deviceId);
        if (machInfo == null){
            AppMach appMach = appMachMapper.selectByMachCode(lastLog.getDeviceCode());
            AppMachDevice appMachDevice = new AppMachDevice();
            appMachDevice.setDeviceId(deviceId);
            appMachDevice.setMachId(appMach.getId());
            appMachDevice.setBindTime(new Date());
            machDeviceMapper.insertSelective(appMachDevice);
            machInfo = machDeviceMapper.selectAppMachInfoByDeviceId(deviceId);
        }
        Integer machId = null != machInfo ? machInfo.getMachId() : 0;

        //插入硬件数据日志
        for (AppMachDataLog log : logList) {
            log.setMachId(machId);
            log.setDelFlag(DelFlag.UNDELETE.getValue());
            log.setNetState(NetState.ONLINE.getValue());
        }
        this.machDataLogManager.addMachDataLog(logList);

        // 在插入硬件数据之后改休眠状态为停机 断电改为停机
        Integer workState = lastLog.getWorkState();
        if (WorkState.SLEEP.getValue().equals(workState) || WorkState.POWER_OFF.getValue().equals(workState)) {
            lastLog.setWorkState(WorkState.STOP.getValue());
        }

        //更新硬件数据
        AppDeviceMachData deviceMachData = new AppDeviceMachData();
        BeanUtils.copyProperties(lastLog, deviceMachData);
        deviceMachDataMapper.insertOrUpdate(deviceMachData);

        //更新机械数据(硬件和机械绑定)
        if (!StringUtils.isEmpty(machId) && machId > 0) {

            //更新设备实时数据
            this.updateMachData(machInfo, serverTime, lastLog);

            //硬件数据按日期分组
            Map<Date, List<AppMachDataLog>> dataLogMap = this.groupByDate(logList);
            Set<Map.Entry<Date, List<AppMachDataLog>>> entrySet = dataLogMap.entrySet();
            for (Map.Entry<Date, List<AppMachDataLog>> entry : entrySet) {
                Date day = entry.getKey();
                List<AppMachDataLog> dayLogList = entry.getValue();

                //增加硬件数据缓存
                this.machDataLogManager.addMachDataLogCache(machId, day, dayLogList);

                //更新设备每日数据分段
                this.updateMachDaySegment(machInfo, day);

                //更新设备每日数据
                this.updateMachDay(machInfo, day);
            }

            // 发送设备报警检测数据到队列
            this.pushAlarmCheckMsg(machInfo, lastLog);
        }
    }

    @Override
    public void addMachWarnRotation(Integer deviceId, MachWarnRotation warn) {

        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByDeviceId(deviceId);
        Integer machId = null != machInfo ? machInfo.getMachId() : 0;
        Integer deptId = machInfo.getHoldDeptId();
        // 更新机械数据(硬件和机械绑定)
        if (!ObjectUtils.isEmpty(machId) && machId > 0) {
            MachWarnCheckDTO data = new MachWarnCheckDTO();
            data.setTriggerTime(warn.getWarnTime());
            data.setMachId(machId);
            data.setDeptId(deptId);
            data.setMachCode(machInfo.getMachCode());
            data.setMachType(machInfo.getMachType());
            data.setMachTypeName(machInfo.getMachTypeName());
            data.setMachModelName(machInfo.getMachModelName());
            data.setRotationZ(ZH_PROJECT_ID == deptId ? warn.getRotationX() : warn.getRotationZ());
            data.setRotationX(ZH_PROJECT_ID == deptId ? warn.getRotationZ() : warn.getRotationX());
            amqpTemplate.convertAndSend(QueueConst.ALARM_CHECK_DATA, JSONUtil.toString(data));
        }
    }

    @Override
    public void addMachOilLog(AppMachOilLog oilLog) {
        appMachOilLogMapper.insertSelective(oilLog);
    }

    @Override
    public void statMachDayData(AppMachInfo machInfo, Date date) {
        // 全量更新数据分段
        this.updateMachDaySegment(machInfo, date);

        // 更新每日统计数据
        this.updateMachDay(machInfo, date);
    }

    @Override
    public OilDay computeOil(Integer machId, Date date) {
        // 获取一天的油位数据
        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByMachId(machId);
        List<Oil> oilList = machDataLogManager.getMachOilByDate(machId, date);
        OilStat stat = this.computeOilStat(machInfo, oilList);
        return new OilDay(stat.getOilAdd(), stat.getOilWear());
    }

    @Override
    public OilStat computeOilStat(Integer machId, Date date, Date startTime, Date endTime) {
        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByMachId(machId);
        return this.computeOilStat(machInfo, date, startTime, endTime);
    }

    @Override
    public OilStat computeOilStat(AppMachInfo machInfo, Date date, Date startTime, Date endTime) {
        // 一个小时计算一次油耗
        List<Oil> oilList = machDataLogManager.getMachOilByDate(machInfo.getMachId(), date, startTime, endTime);
        return this.computeOilStat(machInfo, oilList);
    }

    @Override
    public List<OilDay> computeOilList(Integer machId, Date date) {
        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByMachId(machId);

        // 查询工时分段
        List<AppMachDaySegDTO> segDTOList = this.getMachDaySegList(machInfo.getMachId(), date);

        // 修改工作状态
        for (AppMachDaySegDTO segDTO : segDTOList) {
            // 开机(工作和怠机)
            if (MachUtil.isIdleState(segDTO.getWorkState())) {
                segDTO.setWorkState(WorkState.RUN.getValue());
            }
        }

        // 合并分段
        segDTOList = MachSegmentUtil.mergeMachDaySegment(segDTOList);

        // 按工作分段分别计算油耗
        List<OilDay> oilDayList = new ArrayList<>(segDTOList.size());
        for (AppMachDaySegDTO segDTO : segDTOList) {
            List<Oil> oilList = machDataLogManager.getMachOilByDate(machInfo.getMachId(), date, segDTO.getStartTime(), segDTO.getEndTime());
            OilStat oilStat = this.computeOilStat(machInfo, oilList);
            OilDay oilDay = new OilDay();
            oilDay.setOilAdd(oilStat.getOilAdd());
            oilDay.setOilWear(oilStat.getOilWear());
            oilDay.setStartTime(segDTO.getStartTime());
            oilDay.setEndTime(segDTO.getEndTime());
            oilDay.setWorkState(segDTO.getWorkState());
            oilDayList.add(oilDay);
        }
        return oilDayList;
    }

    @Override
    public List<AppMachDaySegDTO> getMachDaySegList(Integer machId, Date date) {
        AppMachDaySeg daySeg = appMachDaySegMapper.selectByMachIdAndDate(machId, date);
        if (daySeg != null) {
            List<AppMachDaySegDTO> segDTOList = JSON.parseArray(daySeg.getSegments(), AppMachDaySegDTO.class);
            return segDTOList;
        }
        return new ArrayList<>();
    }

    @Override
    public List<AppMachDaySegDTO> getMachDaySegList(AppMachInfo machInfo, Date startTime, Date endTime) {
        List<AppMachDataLogDTO> appMachDataLogDTOS = appMachDataLogDao.selectMachDataLogListByMachId(machInfo.getMachId(), startTime, endTime);
        return this.computeSegment(machInfo, appMachDataLogDTOS);
    }

    @Override
    public AppMachDaySegDTO getLastMachDaySeg(Integer machId, Date date) {
        List<AppMachDaySegDTO> machDaySegList = this.getMachDaySegList(machId, date);
        if (machDaySegList.size() > 0) {
            return machDaySegList.get(machDaySegList.size() - 1);
        }
        return null;
    }

    @Override
    public AppMachDaySegDTO getFirstMachDaySeg(Integer machId, Date date) {
        List<AppMachDaySegDTO> machDaySegList = this.getMachDaySegList(machId, date);
        if (machDaySegList.size() > 0) {
            return machDaySegList.get(0);
        }
        return null;
    }

    @Override
    public void saveMachSeg(Integer machId, Date date, List<AppMachDaySegDTO> segDTOList) {
        String segments = JSONUtil.toString(segDTOList);
        AppMachDaySeg daySeg = new AppMachDaySeg();
        daySeg.setMachId(machId);
        daySeg.setDate(date);
        daySeg.setSegments(segments);
        appMachDaySegMapper.insertOrUpdate(daySeg);
    }

    @Override
    public void addOfflineData(Integer machId, Date time) {
        AppMach appMach = appMachMapper.selectByPrimaryKey(machId);
        if (appMach == null) {
            return;
        }
        Date day = DateUtil.getDate(time);

        // 插入数据日志
        AppMachDataLog record = new AppMachDataLog();
        record.setMachId(machId);
        record.setDeviceId(appMach.getDeviceId());
        record.setTime(time);
        record.setNetState(NetState.OFFLINE.getValue());
        record.setDelFlag(DelFlag.UNDELETE.getValue());
        appMachDataLogDao.insert(record);

        // 增加硬件数据缓存
        List<AppMachDataLog> dayLogList = new ArrayList<>();
        dayLogList.add(record);
        machDataLogManager.addMachDataLogCache(machId, day, dayLogList);

        // 更新设备每日数据分段
        AppMachInfo machInfo = new AppMachInfo();
        machInfo.setMachId(machId);
        machInfo.setHoldDeptId(appMach.getHoldDeptId());
        machInfo.setMachType(appMach.getMachType());
        machInfo.setDeviceId(appMach.getDeviceId());
        this.updateMachDaySegment(machInfo, day);

    }

    @Override
    public void amendDeviceData(List<AppMachDataLog> dataList) {
        if (dataList == null || dataList.size() == 0) {
            return;
        }
        for (AppMachDataLog data : dataList) {
            MapLoc location = mapApi.geocode(data.getLng(), data.getLat());
            if (location != null) {
                data.setLocation(location.getAddress());
                data.setProvince(location.getProvince());
                data.setCity(location.getCity());
            }
        }
        // 插入硬件数据日志
        machDataLogManager.addMachDataLog(dataList);

        AppMachDataLog data = dataList.get(dataList.size() - 1);
        Integer machId = data.getMachId();
        Integer deviceId = data.getDeviceId();
        Date time = data.getTime();
        Date date = DateUtil.getDate(time);

        // 删除缓存数据
        machDataLogManager.delMachDataLogCache(machId, date);
        // 更新设备每日数据分段
        AppMachInfo machInfo = machDeviceMapper.selectAppMachInfoByDeviceId(deviceId);
        this.updateMachDaySegment(machInfo, date);
        // 更新设备每日数据
        this.updateMachDay(machInfo, date);
    }


    /**
     * 硬件数据按日期分组
     *
     * @param machDataLogList
     * @return
     */
    private Map<Date, List<AppMachDataLog>> groupByDate(List<AppMachDataLog> machDataLogList) {
        Map<Date, List<AppMachDataLog>> map = new HashMap<>(machDataLogList.size());
        for (AppMachDataLog log : machDataLogList) {
            Date date = DateUtil.getDate(log.getTime());
            List<AppMachDataLog> logList = map.get(date);
            if (logList == null) {
                logList = new ArrayList<>(machDataLogList.size());
            }
            logList.add(log);
            map.put(date, logList);
        }
        return map;
    }

    /**
     * 更新设备实时数据
     *
     * @param machInfo
     * @param serverTime
     * @param lastLog
     */
    private void updateMachData(AppMachInfo machInfo, Date serverTime, AppMachDataLog lastLog) {
        Integer machId = machInfo.getMachId();
        Integer deviceId = lastLog.getDeviceId();
        AppMachData machData = appMachDataMapper.selectByMachId(machId);
        if (machData == null) {
            machData = new AppMachData();
        }
        Integer oldWorkState = machData.getWorkState();
        Integer newWorkState = lastLog.getWorkState();
        Integer oldNetState = machData.getNetState();
        Integer newNetState = NetState.ONLINE.getValue();

        //验证硬件时间
        Date logTime = lastLog.getTime();
        Date latestLogTime = machData.getTime();
        //历史数据(更新网络状态)
        if (MachUtil.isHistoryDataTime(logTime, latestLogTime)) {
            logger.info("硬件时间不正确,deviceId:{},machId:{},latestLogTime:{},logTime:{}", deviceId, machId, latestLogTime, logTime);
            machData.setMachId(machId);
            machData.setDeviceId(deviceId);
            machData.setNetState(NetState.ONLINE.getValue());
            machData.setUpdateTime(serverTime);
            appMachDataMapper.insertOrUpdate(machData);
            return;
        }
        //最新数据(更新工作状态和所有硬件数据)
        else {
            //工作状态
            if (lastLog.getWorkState() != null && MachUtil.isValidState(lastLog.getWorkState())) {
                WorkStrategy strategy = machStrategyMgr.getWorkStrategy(machInfo.getHoldDeptId(), machInfo.getMachType());
                machData.setWorkState(strategy.amend(lastLog.getWorkState()));
            }
            //工作状态-变化时间
            if (oldWorkState == null || machData.getWorkStateStartTime() == null || !MachUtil.isSameState(oldWorkState, newWorkState)) {
                machData.setWorkStateStartTime(logTime);
            }
            //网络状态-变化时间
            if (oldNetState == null || machData.getNetStateStartTime() == null || !newNetState.equals(oldNetState)) {
                machData.setNetStateStartTime(serverTime);
            }
            //经纬度
//            String polygonWKT = machConfigManager.getPolygonWKT(machInfo.getHoldDeptId(), machInfo.getMachTypeName());
//            if (PositionUtil.contains(FenceType.POLYGON.value(), polygonWKT, null, lastLog.getLat(), lastLog.getLng())) {
                machData.setLngFlag(lastLog.getLngFlag());
                machData.setLng(lastLog.getLng());
                machData.setLatFlag(lastLog.getLatFlag());
                machData.setLat(lastLog.getLat());
                machData.setLngWgs84(lastLog.getLngWgs84());
                machData.setLatWgs84(lastLog.getLatWgs84());
                machData.setLocation(lastLog.getLocation());
                machData.setProvince(lastLog.getProvince());
                machData.setCity(lastLog.getCity());
                machData.setGpsTime(logTime);
//            }
            //电池状态
            if (lastLog.getBatteryState() != null) {
                machData.setBatteryState(lastLog.getBatteryState());
            }
            //电池电量
            if (lastLog.getBatteryPower() != null && lastLog.getBatteryPower() > 0 && lastLog.getBatteryPower() <= 100) {
                machData.setBatteryPower(lastLog.getBatteryPower());
            }
            //设备温度
            if (lastLog.getDeviceTemp() != null) {
                machData.setDeviceTemp(lastLog.getDeviceTemp());
            }
            //油位
            if (lastLog.getOilPos() != null && lastLog.getOilPos() > 0) {
                machData.setOilPos(lastLog.getOilPos());
            }
            //油箱压力
            if (lastLog.getPressure() != null) {
                machData.setPressure(lastLog.getPressure());
            }
            //油箱盖温度
            if (lastLog.getOilTemp() != null) {
                machData.setOilTemp(lastLog.getOilTemp());
            }
            //油箱盖电量
            if (lastLog.getOilPower() != null && lastLog.getOilPower() > 0) {
                machData.setOilPower(lastLog.getOilPower());
            }
            //油箱盖状态
            if (lastLog.getOilState() != null) {
                machData.setOilState(lastLog.getOilState());
            }
            machData.setTime(logTime);
            machData.setMachId(machId);
            machData.setDeviceId(deviceId);
            machData.setNetState(NetState.ONLINE.getValue());
            machData.setUpdateTime(serverTime);
            appMachDataMapper.insertOrUpdate(machData);
        }
    }

    /**
     * 更新设备工时
     *
     * @param machInfo
     * @param date
     */
    private void updateMachDaySegment(AppMachInfo machInfo, Date date) {
        Integer machId = machInfo.getMachId();
        //查询硬件日志
        List<AppMachDataLogDTO> logList = machDataLogManager.getMachDataLogCache(machId, date);
        if (logList.size() > 0) {
            //计算工时
            List<AppMachDaySegDTO> segDTOList = this.computeSegment(machInfo, logList);
            //保存工时分段
            String segments = JSONUtil.toString(segDTOList);
            AppMachDaySeg daySeg = new AppMachDaySeg();
            daySeg.setMachId(machId);
            daySeg.setDate(date);
            daySeg.setSegments(segments);
            appMachDaySegMapper.insertOrUpdate(daySeg);

            // 最新工时分段
            int size = segDTOList.size();
            if (size > 0) {
                AppMachDaySegDTO appMachDaySegDTO = segDTOList.get(size - 1);
                Integer times = appMachDaySegDTO.getTimes();
                machInfo.setTimes(times);
            }
        }
    }

    /**
     * 更新设备每日数据
     *
     * @param machInfo
     * @param date
     */
    private void updateMachDay(AppMachInfo machInfo, Date date) {

        // 设备信息
        Integer machId = machInfo.getMachId();
        // 工作时长
        List<AppMachDaySegDTO> segDTOList = this.getMachDaySegList(machId, date);
        int workTimes = segDTOList.stream()
                .filter(seg -> MachUtil.isRunState(seg.getWorkState()))
                .mapToInt(seg -> seg.getTimes())
                .sum();
        int idleTimes = segDTOList.stream()
                .filter(seg -> MachUtil.isIdleState(seg.getWorkState()))
                .mapToInt(seg -> seg.getTimes())
                .sum();

        // 获取一天的油位数据
        List<Oil> oilList = machDataLogManager.getMachOilByDate(machInfo.getMachId(), date);
        OilStat stat = this.computeOilStat(machInfo, oilList);
        double oilWear = stat.getOilWear();
        double oilAdd = stat.getOilAdd();
        double efficExp = this.computeEfficExp(workTimes, idleTimes);
        double stabExp = this.computeStabExp(machInfo, date);
        double oilExp = this.computeOilExp(oilWear, workTimes, idleTimes);
        double safeExp = this.computeSafeExp(machId);
        double strengthExp = this.computeStrengthExp(workTimes, idleTimes);
        double generalExp = this.computeGeneralExp(efficExp, stabExp, oilExp, safeExp, strengthExp);
        AppMachDay machDay = new AppMachDay();
        machDay.setHoldDeptId(machInfo.getHoldDeptId());
        machDay.setMachId(machId);
        machDay.setDate(date);
        machDay.setWorkTimes(workTimes);
        machDay.setIdleTimes(idleTimes);
        machDay.setOilWear(oilWear);
        machDay.setOilAdd(oilAdd);
        machDay.setYeildExp(0D);
        machDay.setEfficExp(efficExp);
        machDay.setStabExp(stabExp);
        machDay.setOilExp(oilExp);
        machDay.setSafeExp(safeExp);
        machDay.setStrengthExp(strengthExp);
        machDay.setGeneralExp(generalExp);
        machDay.setDeviceId(machInfo.getDeviceId());
        machDayMapper.insertUpdate(machDay);
    }

    /**
     * 计算工时
     *
     * @param machInfo
     * @param logList
     * @return
     */
    private List<AppMachDaySegDTO> computeSegment(AppMachInfo machInfo, List<AppMachDataLogDTO> logList) {
        if (logList.size() > 0) {
            for (AppMachDataLogDTO machDataLogDTO : logList) {
                Integer workState = machDataLogDTO.getWorkState();
                if (WorkState.SLEEP.getValue().equals(workState) || WorkState.POWER_OFF.getValue().equals(workState)) {
                    machDataLogDTO.setWorkState(WorkState.STOP.getValue());
                }
            }
            // 硬件工时分段
            List<AppMachDaySegDTO> segList = MachSegmentUtil.separateMachDaySegment(logList);
            // 获取设备网络状态分段
            List<AppMachDaySegDTO> networkSegment = MachSegmentUtil.separateNetworkSegment(logList);
            // 综合工作状态和网络状态分段
            List<AppMachDaySegDTO> appMachDaySegDTOS = MachSegmentUtil.separateWorkStateAndNetState(segList, networkSegment);
            // 修正工时分段
            Integer machType = machInfo.getMachType();
            Integer deptId = machInfo.getHoldDeptId();
            WorkStrategy workStrategy = machStrategyMgr.getWorkStrategy(deptId, machType);
            List<AppMachDaySegDTO> list = workStrategy.amend(appMachDaySegDTOS);
            // 过滤短时间离线分段
            List<AppMachDaySegDTO> appMachDaySegDTOS1 = MachSegmentUtil.amendOfflineDataSegment(list);
            return appMachDaySegDTOS1;
        }
        return Collections.emptyList();
    }

    /**
     * 计算油量
     *
     * @param machInfo
     * @param oilList
     * @return
     */
    private OilStat computeOilStat(AppMachInfo machInfo, List<Oil> oilList) {
        OilStrategy oilStrategy = machStrategyMgr.getOilStrategy(machInfo.getHoldDeptId(), machInfo.getMachType());
        AppMachOilLookup lookup = machMgr.getOilLookup(machInfo.getMachId(), machInfo.getOilTankHeight(), machInfo.getOilTankVolume());
        OilStat oilStat = oilStrategy.compute(oilList, machInfo.getOilTankHeight(), machInfo.getOilTankVolume(), lookup);
        logger.info("machId:{},oilWear:{},oilAdd:{},lookup:{}", machInfo.getMachId(), oilStat.getOilWear(), oilStat.getOilAdd(), lookup.getOilSheetMap().size());
        return oilStat;
    }

    /**
     * 计算生产指数
     *
     * @param workTimes
     * @param lastWorkTimes
     * @return
     */
    private double computeYeildExp(int workTimes, int lastWorkTimes) {
        if (lastWorkTimes > 0) {
            double exp = (double) (workTimes - lastWorkTimes) / (double) lastWorkTimes;
            return MathUtil.round(exp * 100, 1);
        }
        return 0D;
    }

    /**
     * 计算工作效率
     *
     * @param workTimes
     * @param idleTimes
     * @return
     */
    private double computeEfficExp(int workTimes, int idleTimes) {
        if (workTimes + idleTimes <= 0) {
            return 0;
        }
        double exp = (double) workTimes / (double) (workTimes + idleTimes);
        return MathUtil.round(exp * 100, 1);
    }

    /**
     * 计算稳定指数
     *
     * @param machInfo
     * @param endTime
     * @return
     */
    private double computeStabExp(AppMachInfo machInfo, Date endTime) {
        Integer machId = machInfo.getMachId();
        Date startDate = machInfo.getBindTime();
        Date endDate = endTime;
        int bindDays = DateUtil.getDateListBetween(startDate, endDate).size();
        int workDays = machDayMapper.countWorkDays(machId, startDate, endDate);
        if (bindDays > 0) {
            double exp = (double) workDays / (double) bindDays;
            return MathUtil.round(exp * 100, 1);
        }
        return 0D;
    }

    /**
     * 计算油耗指数
     *
     * @param oilWear
     * @param workTimes
     * @param idleTimes
     * @return
     */
    private double computeOilExp(double oilWear, int workTimes, int idleTimes) {
        if (workTimes + idleTimes <= 0) {
            return 0;
        }
        double exp = oilWear * (60 * 60) / (double) (workTimes + idleTimes);
        return MathUtil.round(exp, 1);
    }

    /**
     * 计算安全指数
     *
     * @param machId
     * @return
     */
    private double computeSafeExp(Integer machId) {
        return 1 * 100;
    }

    /**
     * 计算强度指数
     *
     * @param workTimes
     * @param idleTimes
     * @return
     */
    private double computeStrengthExp(int workTimes, int idleTimes) {
        double exp = (double) (workTimes + idleTimes) / (8 * 60 * 60);
        return MathUtil.round(exp * 100, 1);
    }

    /**
     * 计算综合指数
     *
     * @param efficExp
     * @param stabExp
     * @param oilExp
     * @param safeExp
     * @param strengthExp
     * @return
     */
    private double computeGeneralExp(double efficExp, double stabExp, double oilExp, double safeExp, double strengthExp) {
        double exp = efficExp * 0.25 + stabExp * 0.3 + oilExp * 0.1 + safeExp * 0.1 + strengthExp * 0.25;
        return MathUtil.round(exp, 1);
    }

    /**
     * 发送报警检测消息到队列
     *
     * @param machInfo
     * @param lastLog
     */
    private void pushAlarmCheckMsg(AppMachInfo machInfo, AppMachDataLog lastLog) {
        logger.debug("发送设备报警检测数据到队列,machInfo:{},lastLog:{}", machInfo.toString(), lastLog.toString());
        MachWarnCheckDTO data = new MachWarnCheckDTO();
        Integer deptId = machInfo.getHoldDeptId();
        Integer machId = machInfo.getMachId();
        data.setTriggerTime(lastLog.getTime());
        data.setLat(lastLog.getLat());
        data.setLng(lastLog.getLng());
        data.setSpeed(lastLog.getSpeed());
        data.setWorkState(lastLog.getWorkState());
        data.setMachId(machId);
        data.setDeptId(deptId);
        data.setMachCode(machInfo.getMachCode());
        data.setMachType(machInfo.getMachType());
        data.setMachTypeName(machInfo.getMachTypeName());
        data.setMachModelName(machInfo.getMachModelName());
        data.setTimes(machInfo.getTimes());
        amqpTemplate.convertAndSend(QueueConst.ALARM_CHECK_DATA, JSONUtil.toString(data));

    }

}
